﻿using System.Collections.Generic;
using UnityEngine;
using Cysharp.Threading.Tasks;
using System.IO;

namespace FastDev
{
    public class PoolManager : MonoSingleton<PoolManager>, IPoolManager
    {
        private string bundleName = "prefab";
        private string objTag = "(Pool)";
        private Dictionary<string, Stack<GameObject>> poolObjects = new Dictionary<string, Stack<GameObject>>();

        private int eachStackMax = 99;
        /// <summary>
        /// 分配
        /// </summary>
        /// <param name="bundleName"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public GameObject Allocate(string path)
        {
            GameObject poolObject = null;
            string objName = Path.GetFileNameWithoutExtension(path) + objTag;
            if (!poolObjects.ContainsKey(objName))
                poolObjects[objName] = new Stack<GameObject>();
            var stack = poolObjects[objName];
            while (stack.Count > 0)
            {
                poolObject = stack.Pop();
                if (poolObject != null)
                {
                    break;
                }
            }
            if (poolObject == null)
            {
                poolObject = Instantiate(ResManager.Instance.LoadAsset<GameObject>(bundleName, path));
                poolObject.name = objName;
            }

            if (poolObject != null)
            {
                poolObject.SetActive(true);
            }

            return poolObject;
        }

        /// <summary>
        /// 回收
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public void Recycle(GameObject obj)
        {
            if (obj == null)
                return;
            string objName = obj.name;
            if (!objName.Contains(objTag))
                return;
            if (!poolObjects.ContainsKey(objName))
                poolObjects[objName] = new Stack<GameObject>();
            var stack = poolObjects[objName];
            if (stack.Count < eachStackMax && !stack.Contains(obj))
            {
                stack.Push(obj);
                obj.SetActive(false);
                return;
            }
            Destroy(obj.gameObject);
        }

        /// <summary>
        /// 延迟回收
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="millisecondsDelay"></param>
        /// <returns></returns>
        public async UniTaskVoid Recycle(GameObject obj, int millisecondsDelay)
        {
            await UniTask.Delay(millisecondsDelay);
            Recycle(obj);
        }

    }
}